package com.file.delete.utility;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author Administrator
 * @title: DeleteFileTask
 * @projectName delete
 * @description: TODO
 * @date 2019/12/248:59
 */

@Configuration
@EnableScheduling
public class DeleteFileTaskConfiguration {
    // 日志组件
    private final static Logger logger = LoggerFactory.getLogger(DeleteFileTaskConfiguration.class);

    @Value("${delete.directory}")
    private String directory;

    @Value("${delete.retainFileNum}")
    private Integer retainFileNum;

    @Value("${delete.retainFileDayNum}")
    private String retainFileDayNum;

    @Value("${delete.retainFileLogNum}")
    private Integer retainFileLogNum;

    @Value("${delete.fileSuffix}")
    private String retainFileSuffix;

    private static Boolean _isCompressSucess = true;

    private static String _zipFileName = "";

    /**
     * 自定义区域缓存维护
     */
    @Scheduled(fixedRateString = "${com.file.delete.utility.syncTime:60000}", initialDelay = 1000*1)
    public void runAlarmSetCacheSync() {
        try {
            if(!StringUtils.isEmpty(this.directory)){
                List<String> directoryList = Arrays.asList(this.directory.split(";"));
                directoryList.forEach(x -> {
                    for (int i = 0;i < 20;i++) { // 一次压缩文件个数有限，如果文件多于设置的一次压缩的个数会有问题,所以这里多压缩几次 暂定20次
                        if(!StringUtils.isEmpty(x)){
                            boolean bl = compressFileToZip(x); //压缩文件
                            if(bl){
                                deletFile(x);
                                System.out.println("压缩成功");
                            }
                        }
                    }
                });
            }
        } catch (Exception e) {
            logger.error("删除文件报错，异常信息为:".concat(e.toString()));
        }
    }

    private void deletFile(String directory){
        List<String> retainFileSuffixList = StringUtils.isEmpty(this.retainFileSuffix) ? null : Arrays.asList(this.retainFileSuffix.split(";"));
        File file = new File(directory);
        File[] files = file.listFiles((File p)->{
            Boolean isTrue = false;
            if(CollectionUtils.isEmpty(retainFileSuffixList)) {
                isTrue = true;
            }else {
                for (String suffix : retainFileSuffixList) {
                    isTrue = p.isDirectory()||p.getName().toLowerCase().endsWith(suffix);
                    if(isTrue) {
                        break;
                    }
                }
            }
            return isTrue;
        });
        Arrays.sort(files, new Comparator<File>() {
            @Override
                public int compare(File f1, File f2) {
                int isExchange = f2.lastModified() > f1.lastModified() ? 1 : -1;
                return isExchange;
            }
            @Override
            public boolean equals(Object obj) {
                return true;
            }
        });

        List<File> fileList = Arrays.asList(files);
        fileList = fileList.stream().filter(x -> !x.isDirectory()).collect(Collectors.toList());
        if(fileList.size() > this.retainFileNum){
            SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            for (int i = this.retainFileNum;i < fileList.size();i++) {
                File currentFile = fileList.get(i);
                if(currentFile.delete()){
                    logger.info(currentFile.getName() + "已删除,时间:" + format1.format(new Date()));
                }
            }

            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY,-24 * Integer.parseInt(this.retainFileDayNum));
            String deleteMaxDateStr = format.format(calendar.getTime());
            for (int i = 0;i < fileList.size();i++) {
                File currentFile = fileList.get(i);
                String fileName = currentFile.getName();
                if(!StringUtils.isEmpty(currentFile.getName()) && fileName.length() >= 10){
                    String dateStr = fileName.substring(0,10);
                    if(deleteMaxDateStr.compareTo(dateStr) >= 0){
                        if(currentFile.delete()){
                            logger.info(fileName + "已删除,时间:" + format1.format(new Date()));
                        }
                    }
                }
            }
        };
    }
    /**
     * @Title: compressAllFileZip
     * @Description: 传递文件路径压缩文件，传递文件夹路径压缩文件夹，注：空的文件夹不会出现在压缩包内
     * @param @param compresspath 需要压缩的文件夹的目录
     * @return void    返回类型
     * @throws
     */
    public  boolean compressFileToZip(String compresspath) {
        boolean bool = false;
        try {
            ZipOutputStream zipOutput = null;
            File file = new File(compresspath);
//            File file1 = new File(compresspath + getRandomFileName("/"));
//            if (!file1.exists() && file.length()>0){
//                try {
//                    file1.createNewFile();
//                } catch (IOException e) {
//                    System.out.println(".zip创建失败！");
//                    return false;
//                }
//            }
            String zipFileName = "";
            if(file.isDirectory()){
                zipFileName = compresspath + getRandomFileName("/");
                zipOutput = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFileName)));
                compressZip(zipOutput, file, ""); //递归压缩文件夹，最后一个参数传""压缩包就不会有当前文件夹；传file.getName(),则有当前文件夹;
            }else{
                zipOutput = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(compresspath.substring(0, compresspath.lastIndexOf(".")) + ".zip")));
                zipOFile(zipOutput, file); //压缩单个文件
            }

            zipOutput.closeEntry();
            zipOutput.close();
            bool = true;
            if(!_isCompressSucess) {
                new File(zipFileName).delete();
            }else {
                File oldFile = new File(zipFileName);
                String newZipFileName = compresspath + getRandomFileName("/" + _zipFileName);
                if (oldFile.exists() && oldFile.isFile()) {
                    File newFile = new File(newZipFileName);
                    oldFile.renameTo(newFile);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bool;
    }
    /**
     * @Title: zip
     * @Description: 压缩单个文件
     * @param @param zipOutput
     * @param @param file  文件
     * @return void    返回类型
     * @throws
     */
    public  void zipOFile(ZipOutputStream zipOutput, File file) {
        try {
            ZipEntry zEntry = new ZipEntry(file.getName());
            zipOutput.putNextEntry(zEntry);
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[1024];
            int read = 0;
            while((read = bis.read(buffer)) != -1){
                zipOutput.write(buffer, 0, read);
            }
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * @Title: compressZip
     * @Description: 子文件夹中可能还有文件夹，进行递归
     * @param @param zipOutput
     * @param @param file
     * @param @param suffixpath
     * @param @throws IOException
     * @return void    返回类型
     * @throws
     */
    private  void compressZip(ZipOutputStream zipOutput, File file, String suffixpath) {
        File[] listFiles = file.listFiles((File p)->{
            return p.isDirectory()||p.getName().toLowerCase().endsWith("log");
        });
        Arrays.sort(listFiles, new Comparator<File>() {
            @Override
            public int compare(File f1, File f2) {
                int isExchange = f2.lastModified() > f1.lastModified() ? 1 : -1;
                return isExchange;
            }
            @Override
            public boolean equals(Object obj) {
                return true;
            }
        });
        List<File> fileList = Arrays.asList(listFiles);
        fileList = fileList.stream().filter(x -> !x.isDirectory()).collect(Collectors.toList());
        int fileSize = fileList.size();
        _zipFileName = "";
        if(fileSize > this.retainFileLogNum) {
            for (int i = 1;i < (this.retainFileLogNum + 1);i++) {
                File fi = fileList.get(i);
                if(fi.isDirectory() ) {
                    if(suffixpath.equals("")){
                        compressZip(zipOutput, fi, fi.getName());
                    }else{
                        compressZip(zipOutput, fi, suffixpath + File.separator + fi.getName());
                    }
                }else{
                    if(1 == i) {
//                        String[] flieNameArray = fi.getName().split("\\.");
//                        _zipFileName = flieNameArray[0] + "." + (flieNameArray.length >= 2 ? flieNameArray[1] : "");
                        _zipFileName = fi.getName().replace(".log","");
                    }
                    if (i == this.retainFileLogNum) {
                        String[] flieNameArray = fi.getName().split("\\.");
                        _zipFileName += ("_" + fi.getName().replace(".log",""));
                    }
                    zip(zipOutput, fi, suffixpath);
                }
            }
        }
        _isCompressSucess = fileSize > this.retainFileLogNum;
    }
    /**
     * @Title: zip
     * @Description: 压缩的具体操作
     * @param @param zipOutput
     * @param @param file  文件
     * @param @param suffixpath  文件夹拼接路径
     * @return void    返回类型
     * @throws
     */
    public  void zip(ZipOutputStream zipOutput, File file, String suffixpath) {
        try {
            ZipEntry zEntry = null;
            if(suffixpath.equals("")){
                zEntry = new ZipEntry(file.getName());
            }else{
                zEntry = new ZipEntry(suffixpath + File.separator + file.getName());
            }
            zipOutput.putNextEntry(zEntry);
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[1024];
            int read = 0;
            while((read = bis.read(buffer)) != -1){
                zipOutput.write(buffer, 0, read);
            }
            bis.close();
            file.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 生成随机文件名：当前年月日时分秒+五位随机数
     *
     * @return
     */
    public static String getRandomFileName(String fileName) {
        SimpleDateFormat simpleDateFormat;
        simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        Date date = new Date();
        String str = simpleDateFormat.format(date);
        return (fileName + str) + ".zip";
    }
}
